<?php


namespace logicmodel;


use comservice\GetRedis;
use comservice\Response;
use datamodel\Box;
use datamodel\BoxGoods;
use datamodel\BoxOrders;
use datamodel\BoxRecord;
use datamodel\Goods;
use datamodel\OrdersBox;
use datamodel\UsersBox;
use datamodel\UsersGoods;
use think\Db;

class BoxLogic
{
    private $boxData;
    private $boxOrdersData;
    private $boxGoodsData;
    private $boxRecordData;
    private $usersBoxData;
    private $ordersBoxData;
    private $redis;
    public function __construct()
    {
        $this->boxData = new Box();
        $this->boxOrdersData = new BoxOrders();
        $this->boxGoodsData = new BoxGoods();
        $this->boxRecordData = new BoxRecord();
        $this->usersBoxData = new UsersBox();
        $this->ordersBoxData = new OrdersBox();
        $this->redis = GetRedis::getRedis();
    }

    /**
     * 盲盒列表
     * @param $search
     * @param $time_order
     * @param $price_order
     * @param $page
     * @param $pagesize
     * @return array
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function boxList($search,$time_order,$price_order,$page,$pagesize){
        $where['is_del'] = 0;
        $where['is_show'] = 1;
        if(!empty($search)) $where['name'] = ['like','%'.$search.'%'];
        $count = $this->boxData->where($where)->count();
        if($time_order > 0){
            if($time_order == 1){
                $order = ['create_time asc','order asc'];
            }else{
                $order = ['create_time desc','order asc'];
            }

        }elseif ($price_order > 0){
            if($price_order == 1){
                $order = ['price asc','order asc'];
            }else{
                $order = ['price desc','order asc'];
            }
        }else{
            $order = ['order asc'];
        }
        if($count <= 0) return Response::success('暂无数据',['count'=>$count,'data'=>[],'page'=>$page,'pagesize'=>$pagesize]);
        $data = $this->boxData->where($where)
            ->order($order)
            ->field(['id','name','desc','image','sales','stock','surplus','start_time','end_time','price'])
            ->page($page,$pagesize)
            ->select();
        if(!empty($data)){
            $data = collection($data)->toArray();
            $time = date('Y-m-d H:i:s');
            foreach ($data as $k=>$v){
                        if( $time >= $v['start_time']){
                            if($v['surplus'] > 0){
                                $data[$k]['status'] = 1; //售卖中
                                $data[$k]['status_text'] = '抢购中';
                            }else{
                                $data[$k]['status'] = 2; //已售罄
                                $data[$k]['status_text'] = '已售罄';
                            }
                        }else{
                           $diff_time =  strtotime($v['start_time']) - strtotime($time); //时间差
                            if($diff_time >= 86400) {
                                //未开售
                                $data[$k]['status'] = 3; //显示开售时间
                                $data[$k]['status_text'] = '敬请期待 '.date('m.d H:i').' 开售';
                            }else{
                                //未开售
                                $data[$k]['status'] = 4; //显示倒计时
                                $data[$k]['status_text'] = '倒计时';
                                $data[$k]['diff_time'] = $diff_time;
                            }
        
                        }
            }
            $data = addWebSiteUrl($data,['image']);
        }
        return Response::success('暂无数据',['count'=>$count,'data'=>$data,'page'=>$page,'pagesize'=>$pagesize]);
    }

    /**
     * 盲盒详情
     * @param $id
     * @return array
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function boxDetail($id){
        $where['is_del'] = 0;
        $where['is_show'] = 1;
        $where['id'] = $id;
        $data = $this->boxData->where($where)
            ->field(['*'])
            ->find();
        if($data){
            $data = $data->toArray();
                $data = addWebSiteUrl($data,['image','images']);
            $goods = $this->boxGoodsData->alias('bg')
                ->join('goods g','g.id = bg.goods_id')
                ->where(['bg.box_id'=>$id,'bg.is_show'=>1,'bg.is_del'=>0])
                ->field(['bg.rate','g.name','g.image','g.label','g.price'])
                ->order('bg.order asc')
                ->select();
            if(!empty($goods)){
                $goods = collection($goods)->toArray();
                $goods = addWebSiteUrl($goods,['image']);
            }else{
                $goods = [];
            }
            $data['goods'] = $goods;
            $time = date('Y-m-d H:i:s');
            if( $time >= $data['start_time']){
                if($data['surplus'] > 0){
                    $data['status'] = 1; //售卖中
                    $data['status_text'] = '抢购中';
                }else{
                    $data['status'] = 2; //已售罄
                    $data['status_text'] = '已售罄';
                }
            }else{
                $diff_time =  strtotime($data['start_time']) - strtotime($time); //时间差
                if($diff_time >= 86400) {
                    //未开售
                    $data['status'] = 3; //显示开售时间
                    $data['status_text'] = '敬请期待 '.date('m.d H:i').' 开售';
                }else{
                    //未开售
                    $data['status'] = 4; //显示倒计时
                    $data['status_text'] = '倒计时';
                    $data['diff_time'] = $diff_time;
                }
            }
        
            $data['content'] = content($data['content']);
            return Response::success('success',$data);
        }
        return Response::fail('盲盒信息错误');
    }

    /**
     * 盲盒开奖记录
     * @param $box_id
     * @param $page
     * @param $pagesize
     * @return array
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function boxRecord($box_id,$page,$pagesize){
        $count =  $this->boxRecordData->alias('br')
            ->join('goods g','g.id = br.goods_id')
            ->join('users u','u.id = br.uid')
            ->where(['br.box_id'=>$box_id])
            ->count();
        $data = $this->boxRecordData->alias('br')
            ->join('goods g','g.id = br.goods_id')
            ->join('users u','u.id = br.uid')
            ->field(['g.name','br.price','u.nick_name','br.create_time'])
            ->page($page,$pagesize)
            ->order(['br.id desc'])
            ->where(['br.box_id'=>$box_id])
            ->select();
        return Response::success('success',['data'=>$data,'count'=>$count,'page'=>$page,'pagesize'=>$pagesize]);
    }

    /**
     * 会员盲盒列表
     * @param $uid
     * @param $status
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function usersBoxList($uid,$status){
        $where['ub.is_del'] = 0;
        $where['ub.uid'] = $uid;
        if($status > 1){
            $where['ub.status'] = ['in',[2,3,4]];
        }else{
            $where['ub.status'] =['in',[1,5]];
        }
        $data = $this->usersBoxData->alias('ub')
            ->join('box b','b.id = ub.box_id')
            ->where($where)
            ->order(['ub.id desc'])
            ->field(['ub.id','ub.status','ub.price','b.name','b.image','ub.is_show'])
            ->select();
        if($data){
            $data = collection($data)->toArray();
            $data = addWebSiteUrl($data,['image']);
            return Response::success('success',$data);
        }
        return Response::success('暂无数据',[]);
    }
    /**
     * 盲盒信息
     * @param $uid
     * @param $id
     * @return array
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function userBoxDetail($uid,$id){
        $where['ub.id'] = $id;
        $where['ub.uid'] = $uid;
        $field = ['b.*','ub.price','ub.is_show','ub.status','ub.id','b.id box_id'];
        $data = $this->usersBoxData->alias('ub')
            ->join('box b','b.id = ub.box_id')
            ->where($where)
            ->field($field)
            ->find();
        if($data){
            $data = $data->toArray();
            $data = addWebSiteUrl($data,['image']);
            $goods = $this->boxGoodsData->alias('bg')
                ->join('goods g','g.id = bg.goods_id')
                ->where(['bg.box_id'=>$id,'bg.is_show'=>1,'bg.is_del'=>0])
                ->field(['bg.rate','g.name','g.image','g.label','g.price'])
                ->order('bg.order asc')
                ->select();
            if(!empty($goods)){
                $goods = collection($goods)->toArray();
                $goods = addWebSiteUrl($goods,['image']);
                $data['goods'] = $goods;
            }else{
                $data['goods'] = [];
            }
            return Response::success('success',$data);
        }
        return Response::fail('盲盒信息错误');

    }


    /**
     *购买盲盒
     * @param $userInfo
     * @param $id
     * @param $pay_type
     * @return array
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \GuzzleHttp\Exception\GuzzleException
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     */
    public function apply($userInfo,$id,$pay_type){
        if($userInfo['is_auth'] == 0) return Response::bindAuth();
        if($this->redis->getItem('box_order_'.$userInfo['id'])){
            return Response::fail('频繁操作');
        }
        $this->redis->setItem('box_order_'.$userInfo['id'],0);
        $this->redis->settime('box_order_'.$userInfo['id'],3);
        $info =  $this->boxData->where(['is_del'=>0,'is_show'=>1,'id'=>$id])->find();
        if(empty($info)) return Response::fail('盲盒信息错误');
        $time = date('Y-m-d H:i:s');
        if($time < $info['start_time']) return Response::fail('未到开售时间');
        if($info['surplus'] <= 0) return Response::fail('已售罄');
        $uid = $userInfo['id'];
        $order_num = uniqueNum();
        $time = date('Y-m-d H:i:s');
        if($pay_type == 1){
            Db::startTrans();
            $result = (new AccountLogic())->subAccount($uid,1,$info['price'],'购买盲盒','购买盲盒'.$info['name']);
            if(!$result){
                Db::rollback();
                return Response::fail('余额不足');
            }
            $order['uid'] = $uid;
            $order['box_id'] = $id;
            $order['order_num'] = $order_num;
            $order['status'] = 1;
            $order['pay_type'] = $pay_type;
            $order['create_time'] = $time;
            $order['pay_time'] = $time;
            $order['price'] = $info['price'];
            $result = $this->ordersBoxData->insertGetId($order);
            if(!$result){
                Db::rollback();
                return Response::fail('购买失败');
            }

            $box['uid'] = $uid;
            $box['box_id'] = $id;
            $box['price'] = $info['price'];
            $box['create_time'] = $time;
            $result =  $this->usersBoxData->insertGetId($box);
            if($result){
                Db::commit();
                $this->boxData->where(['id'=>$id])->setInc('sales',1);
                $this->boxData->where(['id'=>$id])->setDec('surplus',1);
                return Response::success('购买成功',['is_pay'=>1]);
            }
            Db::rollback();
            return Response::fail('购买失败');
        }elseif($pay_type == 2){
            if($userInfo['is_wx_auth'] == 0 || empty($userInfo['wx_open_id'])) return Response::wxAuth();
            //生成支付信息
            $notify_url = config('site.wx_orders_box_notify');
            $pay =  (new WxLogic())->pay($order_num,'购买盲盒'.$info['name'],$info['price'],$userInfo['wx_open_id'],$notify_url);
            if($pay === false) return Response::fail('订单生成失败');
            $order['uid'] = $uid;
            $order['box_id'] = $id;
            $order['order_num'] = $order_num;
            $order['pay_type'] = $pay_type;
            $order['create_time'] = $time;
            $order['price'] = $info['price'];
            $result = $this->ordersBoxData->insertGetId($order);
            if(!$result){
                return Response::fail('购买失败');
            }
            return Response::success('success',['is_pay'=>0,'pay'=>$pay]);
        }elseif ($pay_type == 3){
            //微信APP支付
            //生成支付信息
            $notify_url = config('site.wx_app_orders_box_notify');
            $pay =  (new WxLogic())->pay($order_num,'购买盲盒'.$info['name'],$info['price'],$userInfo['wx_open_id'],$notify_url);
            if($pay === false) return Response::fail('订单生成失败');
            $order['uid'] = $uid;
            $order['box_id'] = $id;
            $order['order_num'] = $order_num;
            $order['pay_type'] = $pay_type;
            $order['create_time'] = $time;
            $order['price'] = $info['price'];
            $result = $this->ordersBoxData->insertGetId($order);
            if(!$result){
                return Response::fail('购买失败');
            }
            return Response::success('success',['is_pay'=>0,'pay'=>$pay]);

        }elseif ($pay_type == 4){
            //支付宝APP支付
            $notify_url = config('site.ali_app_orders_box_notify');
            $pay =  (new AliLogic())->appPay($order_num,'购买盲盒'.$info['name'],$info['price'],$notify_url);
            if($pay === false) return Response::fail('订单生成失败');
            $order['uid'] = $uid;
            $order['box_id'] = $id;
            $order['order_num'] = $order_num;
            $order['pay_type'] = $pay_type;
            $order['create_time'] = $time;
            $order['price'] = $info['price'];
            $result = $this->ordersBoxData->insertGetId($order);
            if(!$result){
                return Response::fail('购买失败');
            }
            return Response::success('success',['is_pay'=>0,'pay'=>$pay]);

        }else{
            return Response::fail('支付方式错误');
        }

    }

    /**
     * 出售盲盒
     * @param $uid
     * @param $id
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function sale($uid,$id,$price){
        $is_trade = config('site.is_trade');
        if($is_trade == 0) return Response::fail('市场未开启');
        if($price < 0.01) return Response::fail('价格输入错误');
        $info = $this->usersBoxData->where(['uid'=>$uid,'id'=>$id,'status'=>1])->find();
        if(empty($info)) return Response::fail('盲盒信息错误');
        $result = $this->usersBoxData->where(['id'=>$id])->update(['status'=>2,'sales_time'=>date('Y-m-d H:i:s'),'price'=>$price]);
        if($result) return Response::success('出售成功');
        return  Response::fail('出售失败');
    }

    /**
     * 修改盲盒价格
     * @param $uid
     * @param $id
     * @param $price
     * @return array
     */
    public function updatePrice($uid,$id,$price){
        if($price < 0.01) return Response::fail('价格输入错误');
        $result =  $this->usersBoxData->where(['uid'=>$uid,'id'=>$id,'status'=>['in',[1,2]]])->update(['price'=>$price]);
        if($result) return Response::success('修改成功');
        return Response::fail('修改失败');
    }

    /**
     * 切换盲盒状态
     * @param $uid
     * @param $id
     * @param $is_show
     * @return array
     */
    public function updateShow($uid,$id,$is_show){
        $result =  $this->usersBoxData->where(['uid'=>$uid,'id'=>$id])->update(['is_show'=>$is_show]);
        if($result) return Response::success($is_show == 1?'上架成功':'下架成功');
        return Response::fail($is_show == 1?'上架失败':'下架失败');
    }

    /**
     * 打开盲盒
     * @param $uid
     * @param $id
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function open($uid,$id){
        $info =  $this->usersBoxData->where(['id'=>$id,'uid'=>$uid,'status'=>['in',[1,2]]])->find();
        if(empty($info)) return Response::fail('盲盒信息错误');
        $boxGoods = $this->boxGoodsData->where(['box_id'=>$info['box_id'],'is_show'=>1,'is_del'=>0])->column('reality_rate','goods_id');
        if(empty($boxGoods)) return Response::fail('藏品信息错误');
        $goods_id =  $this->get_rand($boxGoods);
        Db::startTrans();
        $result = $this->usersBoxData->where(['id'=>$id])->update(['status'=>5]);
        if(!$result){
            Db::rollback();
            return Response::fail('盲盒拆开失败');
        }
        $goodsInfo = (new Goods())->where(['id'=>$goods_id])->find();
        //生成记录
        $box['uid'] = $uid;
        $box['box_id'] = $info['box_id'];
        $box['goods_id'] = $goods_id;
        $box['users_box_id'] = $id;
        $box['price'] = $goodsInfo['price'];
        $box['create_time'] = date('Y-m-d H:i:s');
        $result = $this->boxRecordData->insertGetId($box);
        if(!$result){
            Db::rollback();
            return Response::fail('盲盒拆开失败');
        }
        $goods['uid'] = $uid;
        $goods['goods_id'] = $goods_id;
        $goods['price'] =  $goodsInfo['price'];
        $goods['create_time'] = date('Y-m-d H:i:s');
        $goods['goods_num'] = 0;
        $result = (new UsersGoods())->insertGetId($goods);
        if($result){
            Db::commit();
            $data['name'] = $goodsInfo['name'];
            $data['image'] = $goodsInfo['image'];
            $data['price'] = $goodsInfo['price'];
            $data = addWebSiteUrl($data,['image']);
            return Response::success('恭喜获得'.$goodsInfo['name'],$data);
        }
        Db::rollback();
        return Response::fail('盲盒拆开失败');
    }


    /**
     * 随机获得商品碎片
     * @param $proArr
     * @return int|string
     */
    public  function get_rand($proArr) {
        $result = '';
        //概率数组的总概率精度
        $proSum = array_sum($proArr);
        //概率数组循环
        foreach ($proArr as $key => $proCur) {
            $randNum = mt_rand(1, $proSum);
            if ($randNum <= $proCur) {
                $result = $key;
                break;
            } else {
                $proSum -= $proCur;
            }
        }
        unset ($proArr);
        return $result;
    }
}